package site.isscloud.project.mqtt;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import site.isscloud.framework.mqtt.MqttMessageHandler;
import site.isscloud.project.mqtt.dto.TemperatureMqttDto;
import site.isscloud.project.service.IPjRealtimeTemperatureService;

import java.util.Date;
import java.util.Map;

/**
 * 项目MQTT消息处理器
 */
@Component
public class ProjectMqttMessageHandler implements MqttMessageHandler {

    private static final Logger log = LoggerFactory.getLogger(ProjectMqttMessageHandler.class);

    @Autowired
    private IPjRealtimeTemperatureService temperatureService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private Environment environment;

    private final ObjectMapper objectMapper = new ObjectMapper();

    // 实时数据时间容忍度（30秒）
    private final long REALTIME_MESSAGE_TIME_TOLERANCE = 30000;

    @Override
    public void handleMessage(String topic, String payload, int qos) {
        log.info("业务模块处理MQTT消息 - Topic: {}, Payload: {}, QoS: {}", topic, payload, qos);

        try {
            if (topic.contains("isscloud/elevator/realtime")) {
                // 实时数据：检查createTime与当前时间间隔
                if (isRealtimeDataExpired(payload)) {
                    log.warn("丢弃过期实时数据 - Topic: {}", topic);
                    return;
                }
                handleRealtimeData(payload);
            } else if (topic.contains("isscloud/elevator/alarm")) {
                // 告警数据：不忽略，直接处理
                handleAlarmData(payload);
            } else {
                log.warn("未知主题的消息: {}", topic);
            }
        } catch (Exception e) {
            log.error("处理MQTT消息异常 - Topic: {}", topic, e);
        }
    }

    /**
     * 检查实时数据是否过期（createTime与当前时间间隔超过30秒）
     */
    private boolean isRealtimeDataExpired(String payload) {
        try {
            TemperatureMqttDto temperatureData = objectMapper.readValue(payload, TemperatureMqttDto.class);
            Date createTime = temperatureData.getCreateTime();

            if (createTime != null) {
                long timeDiff = System.currentTimeMillis() - createTime.getTime();
                if (timeDiff > REALTIME_MESSAGE_TIME_TOLERANCE) {
                    log.warn("实时数据过期 - 时间差: {}ms, 设备: {}, 通道: {}",
                            timeDiff, temperatureData.getDeviceNo(), temperatureData.getChannelNo());
                    return true;
                }
            }
        } catch (Exception e) {
            log.debug("解析实时数据时间失败，按未过期处理: {}", e.getMessage());
        }

        return false;
    }

    /**
     * 处理实时数据 - 温度数据
     */
    private void handleRealtimeData(String payload) {
        log.info("=== 开始处理温度实时数据 ===");

        try {
            TemperatureMqttDto temperatureData = objectMapper.readValue(payload, TemperatureMqttDto.class);

            log.info("收到温度数据 - 设备: {}, 通道: {}, 温度数组长度: {}, 时间: {}",
                    temperatureData.getDeviceNo(),
                    temperatureData.getChannelNo(),
                    temperatureData.getMaxTemperatures().size(),
                    temperatureData.getCreateTime());

            temperatureService.processMqttTemperatureData(temperatureData);

        } catch (Exception e) {
            log.error("处理温度实时数据失败: {}", payload, e);
        }
    }

    /**
     * 处理告警数据 - 不进行时间检查
     */
    private void handleAlarmData(String payload) {
        log.info("=== 开始处理电梯告警数据 ===");

        try {
            Map<String, Object> alarmData = objectMapper.readValue(payload, Map.class);

            // 提取通用告警信息
            String deviceNo = getStringValue(alarmData, "deviceNo");
            Integer channel = getIntegerValue(alarmData, "chanel");
            Integer alarmType = getIntegerValue(alarmData, "alarmType");

            log.info("收到告警数据 - 设备: {}, 通道: {}, 告警类型: {}",
                    deviceNo, channel, alarmType);

            // 根据告警类型分发处理
            if (alarmType != null) {
                switch (alarmType) {
                    case 1: // 断纤告警
                        handleFiberBreakAlarm(deviceNo, channel, alarmData);
                        break;
                    case 2: // 激光器故障告警
                        handleLaserFaultAlarm(deviceNo, channel, alarmData);
                        break;
                    case 3: // 温度告警
                        handleTemperatureAlarm(deviceNo, channel, alarmData);
                        break;
                    default:
                        log.warn("未知告警类型: {}", alarmType);
                        break;
                }
            } else {
                log.warn("告警类型为空");
            }

        } catch (Exception e) {
            log.error("处理告警数据失败: {}", payload, e);
        }
    }

    /**
     * 处理断纤告警 (alarmType = 1)
     */
    private void handleFiberBreakAlarm(String deviceNo, Integer channel, Map<String, Object> alarmData) {
        try {
            Integer fiberBreakPosition = getIntegerValue(alarmData, "fiberBreakPosition");
            String sData = getStringValue(alarmData, "sData");

            log.info("处理断纤告警 - 设备: {}, 通道: {}, 断纤位置: {}",
                    deviceNo, channel, fiberBreakPosition);

            // 调用HTTP接口处理告警数据
            boolean success = sendAlarmToHttpController(alarmData);

            if (success) {
                log.info("断纤告警处理完成 - 设备: {}, 通道: {}", deviceNo, channel);
            } else {
                log.error("断纤告警处理失败 - 设备: {}, 通道: {}", deviceNo, channel);
            }

            // 记录详细告警信息
            if (sData != null) {
                log.debug("断纤告警详情: {}", sData);
            }

        } catch (Exception e) {
            log.error("处理断纤告警失败 - 设备: {}, 通道: {}", deviceNo, channel, e);
        }
    }

    /**
     * 处理激光器故障告警 (alarmType = 2)
     */
    private void handleLaserFaultAlarm(String deviceNo, Integer channel, Map<String, Object> alarmData) {
        try {
            Integer laserTemperature = getIntegerValue(alarmData, "laserTemperature");
            String sData = getStringValue(alarmData, "sData");

            log.info("处理激光器故障告警 - 设备: {}, 通道: {}, 激光器温度: {}°C",
                    deviceNo, channel, laserTemperature);

            // 调用HTTP接口处理告警数据
            boolean success = sendAlarmToHttpController(alarmData);

            if (success) {
                log.info("激光器故障告警处理完成 - 设备: {}, 通道: {}", deviceNo, channel);
            } else {
                log.error("激光器故障告警处理失败 - 设备: {}, 通道: {}", deviceNo, channel);
            }

            // 记录详细告警信息
            if (sData != null) {
                log.debug("激光器故障告警详情: {}", sData);
            }

        } catch (Exception e) {
            log.error("处理激光器故障告警失败 - 设备: {}, 通道: {}", deviceNo, channel, e);
        }
    }

    /**
     * 处理温度告警 (alarmType = 3)
     */
    private void handleTemperatureAlarm(String deviceNo, Integer channel, Map<String, Object> alarmData) {
        try {
            Integer meterMark = getIntegerValue(alarmData, "meterMark");
            Object meterAlarmTemperature = alarmData.get("meterAlarmTemperature");
            Integer meterAlarmStatus = getIntegerValue(alarmData, "meterAlarmStatus");
            String sData = getStringValue(alarmData, "sData");

            log.info("处理温度告警 - 设备: {}, 通道: {}, 米标: {}, 温度: {}, 状态: {}",
                    deviceNo, channel, meterMark, meterAlarmTemperature, meterAlarmStatus);

            // 调用HTTP接口处理告警数据
            boolean success = sendAlarmToHttpController(alarmData);

            if (success) {
                log.info("温度告警处理完成 - 设备: {}, 通道: {}, 米标: {}", deviceNo, channel, meterMark);
            } else {
                log.error("温度告警处理失败 - 设备: {}, 通道: {}, 米标: {}", deviceNo, channel, meterMark);
            }

            // 记录详细告警信息
            if (sData != null) {
                log.debug("温度告警详情: {}", sData);
            }

        } catch (Exception e) {
            log.error("处理温度告警失败 - 设备: {}, 通道: {}", deviceNo, channel, e);
        }
    }

    /**
     * 发送告警数据到HTTP控制器进行处理
     */
    private boolean sendAlarmToHttpController(Map<String, Object> alarmData) {
        try {
            // 从配置中获取端口，如果没有配置则使用默认值8080
            String port = environment.getProperty("server.port", "8080");
            String url = "http://localhost:" + port + "/project/alarm/simulate/receive";

            log.debug("调用告警接口URL: {}", url);

            // 创建请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);

            // 创建请求实体
            HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(alarmData, headers);

            // 发送POST请求
            ResponseEntity<Map> response = restTemplate.postForEntity(url, requestEntity, Map.class);

            if (response.getStatusCode().is2xxSuccessful()) {
                Map<String, Object> responseBody = response.getBody();
                if (responseBody != null && "success".equals(responseBody.get("code"))) {
                    log.info("HTTP接口处理告警成功 - 设备: {}, 类型: {}",
                            alarmData.get("deviceNo"), alarmData.get("alarmType"));
                    return true;
                }
            }

            log.error("HTTP接口返回异常 - 状态码: {}, 响应: {}", response.getStatusCode(), response.getBody());
            return false;

        } catch (Exception e) {
            log.error("调用告警HTTP接口失败", e);
            return false;
        }
    }

    private String getStringValue(Map<String, Object> data, String key) {
        Object value = data.get(key);
        return value != null ? value.toString() : null;
    }

    private Integer getIntegerValue(Map<String, Object> data, String key) {
        Object value = data.get(key);
        if (value == null) {
            return null;
        }
        if (value instanceof Integer) {
            return (Integer) value;
        }
        try {
            return Integer.parseInt(value.toString());
        } catch (NumberFormatException e) {
            log.warn("字段 {} 的值 {} 无法转换为整数", key, value);
            return null;
        }
    }
}